package com.ambitor.ipro.view;

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.json.annotations.JSON;

import com.ambitor.ipro.util.Constants;

/**
 * 与具体ORM实现无关的分页参数及查询结果封装.
 * 
 * @param <T>
 *            Pager中记录的类型.
 * @author bugxiaoya@gmail.com
 */
public final class Pager {

	// 分页参数
	private int curPageNo = 1; // 当前所在页码（在第几页）

	private int pageSize = Constants.PAGER_MIN_PAGESIZE; // 当前每页显示的记录数

	private int totalCount = 0; // 记录总数

	private transient String orderBy = null; // 排序字段

	private transient String order = null; // 排序方式（升序或降序）

	public Pager() {
		super();
	}

	public Pager(final int pageSize, final int totalCount) {
		setPageSize(pageSize);
		setTotalCount(totalCount);
	}

	/**
	 * 获得当前页的页号,序号从1开始,默认为1.
	 */
	public int getCurPageNo() {
		return curPageNo;
	}

	/**
	 * 设置当前页的页号,序号从1开始,低于1时自动调整为1.
	 * 
	 * @param curPageNo
	 */
	public void setCurPageNo(final int curPageNo) {
		this.curPageNo = curPageNo;

		if (curPageNo < 1) {
			this.curPageNo = 1;
		}
	}

	/**
	 * 获得每页的记录数量,默认为10.
	 */
	public int getPageSize() {
		return pageSize;
	}

	/**
	 * 设置每页的记录数量,超出MIN_PAGESIZE与MAX_PAGESIZE范围时会自动调整.
	 * 
	 * @param pageSize
	 */
	public void setPageSize(final int pageSize) {
		this.pageSize = pageSize;

		if (pageSize < Constants.PAGER_MIN_PAGESIZE) {
			this.pageSize = Constants.PAGER_MIN_PAGESIZE;
		} else if (pageSize > Constants.PAGER_MAX_PAGESIZE) {
			this.pageSize = Constants.PAGER_MAX_PAGESIZE;
		}
	}

	/**
	 * 根据curPageNo和pageSize（每页显示记录数）计算当前页第一条记录在总结果集中的位置,序号从0开始.
	 */
	@JSON(serialize = false)
	public int getFirst() {
		int start = (curPageNo - 1) * pageSize;
		if (start > this.getTotalCount())
			start = 0;
		return start;
	}

	@JSON(serialize = false)
	public int getEnd() {
		int first = getFirst();
		int end = first + pageSize;
		if ((first + pageSize) > this.getTotalCount())
			end = this.getTotalCount();
		return end;
	}

	/**
	 * 获得排序字段,无默认值。多个排序字段时用','分隔
	 */
	@JSON(serialize = false)
	public String getOrderBy() {
		return this.orderBy;
	}

	/**
	 * 设置排序字段。多个排序字段时用','分隔
	 * 
	 * @param orderBy
	 *            要排序的字段
	 */
	public void setOrderBy(final String orderBy) {
		this.orderBy = orderBy;
	}

	/**
	 * 是否已设置排序字段,仅在Criterion查询时有效.
	 */
	@JSON(serialize = false)
	public boolean isOrderBySetted() {
		return StringUtils.isNotBlank(orderBy); // isNotBlank判断：当orderBy不等于null、""或" "时返回true
	}

	/**
	 * 获得排序方向,默认为asc
	 */
	@JSON(serialize = false)
	public String getOrder() {
		return this.order;
	}

	/**
	 * 设置排序方式向
	 * 
	 * @param order
	 *            可选值为desc或asc，多个排序字段时用','分隔.
	 */
	public void setOrder(final String order) {
		// 检查order字符串的合法值
		String[] orders = StringUtils.split(StringUtils.lowerCase(order), ',');
		for (String orderStr : orders) {
			if (!StringUtils.equals(Constants.PAGER_DESC, orderStr)
					&& !StringUtils.equals(Constants.PAGER_ASC, orderStr))
				throw new IllegalArgumentException("排序方向" + orderStr + "不是合法值");
		}

		this.order = StringUtils.lowerCase(order);
	}

	/**
	 * 取得总记录数,默认值为-1.
	 */
	public int getTotalCount() {
		return totalCount;
	}

	/**
	 * 设置总记录数
	 * 
	 * @param totalCount
	 */
	public void setTotalCount(final int totalCount) {
		this.totalCount = totalCount;
	}

	/**
	 * 根据pageSize与totalCount计算总页数,默认值为-1.
	 */
	public int getTotalPages() {
		if (totalCount < 0)
			return -1;

		int count = totalCount / pageSize;
		if (totalCount % pageSize > 0) {
			count++;
		}
		return count;
	}

	/**
	 * 是否还有下一页.
	 */
	@JSON(serialize = false)
	public boolean isHasNext() {
		return (curPageNo + 1 <= getTotalPages());
	}

	/**
	 * 取得下页的页号,序号从1开始.
	 */
	@JSON(serialize = false)
	public int getNextPage() {
		if (isHasNext())
			return curPageNo + 1;
		else
			return curPageNo;
	}

	/**
	 * 是否还有上一页.
	 */
	@JSON(serialize = false)
	public boolean isHasPre() {
		return (curPageNo - 1 >= 1);
	}

	/**
	 * 取得上页的页号,序号从1开始.
	 */
	@JSON(serialize = false)
	public int getPrePage() {
		if (isHasPre())
			return curPageNo - 1;
		else
			return curPageNo;
	}
}